package com.tsyz.servlet.domain.vo;

import com.tsyz.servlet.exception.ErrorEnumCode;
import com.tsyz.servlet.util.TraceIdUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.slf4j.MDC;

import java.io.Serializable;

/**
 * 统一响应结果封装
 *
 * @param <T> 数据类型
 * @author ext.zhaoke14
 */
@Data
@Accessors(chain = true)
public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 状态码
     */
    private Integer code;

    /**
     * 标题,可为空
     */
    private String title;

    /**
     * 响应消息,可为空
     */
    private String message;

    /**
     * 响应数据
     */
    private T data;

    /**
     * 是否成功
     */
    private Boolean success;

    /**
     * traceId
     */
    private String traceId;

    /**
     * 默认构造函数
     */
    public Result() {
        this.traceId = getCurrentTraceId();
    }

    /**
     * 使用ErrorCode的构造函数
     */
    public Result(ErrorEnumCode errorEnumCode, T data, Boolean success) {
        this.code = errorEnumCode.getCode();
        this.title = errorEnumCode.getTitle();
        this.message = errorEnumCode.getMessage();
        this.data = data;
        this.success = success;
        this.traceId = getCurrentTraceId();
    }

    /* ==================== 成功响应方法 ==================== */

    /**
     * 成功响应（带数据）
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(ErrorEnumCode.SUCCESS, data, true);
    }

    /**
     * 成功响应（无数据）
     */
    public static <T> Result<T> success() {
        return success(null);
    }

    /**
     * 成功响应（自定义消息）
     */
    public static <T> Result<T> success(String message) {
        return new Result<T>()
                .setCode(ErrorEnumCode.SUCCESS.getCode())
                .setTitle(ErrorEnumCode.SUCCESS.getTitle())
                .setMessage(message)
                .setSuccess(true);
    }

    /**
     * 成功响应（自定义消息和数据）
     */
    public static <T> Result<T> success(String message, T data) {
        return success(data).setMessage(message);
    }

    /* ==================== 失败响应方法 ==================== */

    /**
     * 失败响应（默认错误码和消息）
     */
    public static <T> Result<T> error() {
        return error(ErrorEnumCode.UNKNOWN_ERROR);
    }

    /**
     * 失败响应（自定义消息）
     */
    public static <T> Result<T> error(String message) {
        return new Result<T>()
                .setCode(ErrorEnumCode.UNKNOWN_ERROR.getCode())
                .setTitle(ErrorEnumCode.UNKNOWN_ERROR.getTitle())
                .setMessage(message)
                .setSuccess(false);
    }

    /**
     * 失败响应（自定义错误码和消息）
     */
    public static <T> Result<T> error(Integer code, String message) {
        return new Result<T>()
                .setCode(code)
                .setMessage(message)
                .setSuccess(false);
    }

    /**
     * 失败响应（使用预定义错误码）
     */
    public static <T> Result<T> error(ErrorEnumCode errorEnumCode) {
        return new Result<>(errorEnumCode, null, false);
    }

    /**
     * 失败响应（使用预定义错误码，覆盖消息）
     */
    public static <T> Result<T> error(ErrorEnumCode errorEnumCode, String message) {
        Result<T> error = error(errorEnumCode);
        return error.setMessage(message);
    }

    /**
     * 失败响应（使用预定义错误码，附带数据）
     */
    public static <T> Result<T> error(ErrorEnumCode errorEnumCode, T data) {
        return new Result<>(errorEnumCode, data, false);
    }

    /**
     * 失败响应（自定义错误码、消息和数据）
     */
    public static <T> Result<T> error(Integer code, String message, T data) {
        return new Result<T>()
                .setCode(code)
                .setMessage(message)
                .setData(data)
                .setSuccess(false);
    }

    /**
     * 判断响应是否成功
     */
    public boolean isSuccess() {
        return Boolean.TRUE.equals(success);
    }

    /**
     * 获取当前请求的traceId
     */
    private String getCurrentTraceId() {
        return MDC.get(TraceIdUtil.TRACE_ID);
    }
}
